
#include "GLfrustum.h"

void GLfrustum::Update()
{
	GLmat4f proj, view;

	//get matrices
	glGetFloatv(GL_PROJECTION_MATRIX, proj.Base());
	glGetFloatv(GL_MODELVIEW_MATRIX, view.Base());

	MakeFrustum( view,proj );

	m_view = view;
	m_proj = proj;

}
void GLfrustum::MakeFrustum( GLmat4f view,GLmat4f proj )
{
	GLmat4f clip;

	clip = view * proj;

	// the clipping planes we received above and extract the sides from them.

	// This will extract the RIGHT side of the frustum
	planes[RIGHTSIDE].n.x = clip.x[3] - clip.x[0];
	planes[RIGHTSIDE].n.y = clip.y[3] - clip.y[0];
	planes[RIGHTSIDE].n.z = clip.z[3] - clip.z[0];
	planes[RIGHTSIDE].d        = clip.w[3] - clip.w[0];

	planes[LEFTSIDE].n.x = clip.x[3] + clip.x[0];
	planes[LEFTSIDE].n.y = clip.y[3] + clip.y[0];
	planes[LEFTSIDE].n.z = clip.z[3] + clip.z[0];
	planes[LEFTSIDE].d        = clip.w[3] + clip.w[0];

	planes[BOTTOMSIDE].n.x = clip.x[3]  + clip.x[1];
	planes[BOTTOMSIDE].n.y = clip.y[3]  + clip.y[1];
	planes[BOTTOMSIDE].n.z = clip.z[3]  + clip.z[1];
	planes[BOTTOMSIDE].d        = clip.w[3]  + clip.w[1];

	// This will extract the TOP side of the frustum
	planes[TOPSIDE].n.x = clip.x[3] - clip.x[1];
	planes[TOPSIDE].n.y = clip.y[3] - clip.y[1];
	planes[TOPSIDE].n.z = clip.z[3] - clip.z[1];
	planes[TOPSIDE].d        = clip.w[3] - clip.w[1];

	// This will extract the FRONT side of the frustum
	planes[NEARSIDE].n.x = clip.x[3] + clip.x[2];
	planes[NEARSIDE].n.y = clip.y[3] + clip.y[2];
	planes[NEARSIDE].n.z = clip.z[3] + clip.z[2];
	planes[NEARSIDE].d        = clip.w[3] + clip.w[2];

	// This will extract the BACK side of the frustum
	planes[FARSIDE].n.x = clip.x[3] - clip.x[2];
	planes[FARSIDE].n.y = clip.y[3] - clip.y[2];
	planes[FARSIDE].n.z = clip.z[3] - clip.z[2];
	planes[FARSIDE].d        = clip.w[3] - clip.w[2];

	for( int i = 0;i<6;i++ )
	{
		planes[i].Normalize();
	}
}

//is a point in the frustum?
bool GLfrustum::IsPointInside(const GLvec3f & point ) const
{

	for(int i=0; i<6; ++i)
	{
		if(planes[i].IsOnBackSide(point) )
			return false;
	}

	return true;
}

//is a bounding box in the frustum?
bool GLfrustum::IsBoundingBoxInside( const GLbbox& bb ) const
{
	GLvec3f verts[8];
	bb.GetVerts( verts );

	int backs[6];

	for( int j = 0;j<6;j++ )		
	{
		backs[j] = 0;

		for(int i=0; i<8; i++ )
		{	
			GLplanef pl = GetPlane( j );

			if( pl.IsOnBackSide( verts[i] ))
			{
				backs[j] ++;
			}
		}

		if( backs[j] == 8 )
			return false;
	}

	return true;

}
